using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Web.UI.Design;

using PHSRAG.Insight21.CDS;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.ClinicalTrials;

namespace PHSRAG.Insight21.InsightWebControls.ClinicalTrials
{
	/// <summary>
	/// The Budget Expense Control is used to provide a user interface for a single Budget Expense.
	/// </summary>
   [ToolboxData("<{0}:BudgetExpenseControl runat=server></{0}:BudgetExpenseControl>"),Designer(typeof(BudgetExpenseControlDesigner))]
   public class BudgetExpenseControl : System.Web.UI.Control, INamingContainer
   {
      #region Instance Variables
      private BudgetExpense budgetExpense;
      private TableRow tr;
      private TableCell tdDescription;
      private TableCell tdCost;
      private TableCell tdDelete;
      private DropDownList costsList;
      private CheckBox applyOverhead;
      private CheckBox delete;
      private TextBox inputCostAmount;
      private TextBox inputOtherCost;
      private RegularExpressionValidator costFormatValidator;
      private RequiredFieldValidator costRequiredValidator;
      private RequiredFieldValidator descriptionValidator;
      private RequiredFieldValidator otherCostValidator;
      #endregion

      #region Public Properties
      /// <summary>
      /// Apply overhead indicator
      /// </summary>
      public bool ApplyOverhead
      {
         get
         {
            return applyOverhead.Checked;
         }
      }

      /// <summary>
      /// Delete indicator
      /// </summary>
      public bool Delete
      {
         get
         {
            return delete.Checked;
         }
      }
         
      /// <summary>
      /// Expense Cost
      /// </summary>
      public string ExpenseCost
      {
         get
         {
            return inputCostAmount.Text;
         }
      }

      /// <summary>
      /// Other Expense
      /// </summary>
      public string OtherExpense
      {
         get
         {
            return inputOtherCost.Text;
         }
      }
      #endregion

      #region Constructor
      /// <summary>
      /// Sets the private Budget Expense member from the passed in parameter
      /// </summary>
      /// <param name="budgetExpense"></param>
      public BudgetExpenseControl( BudgetExpense budgetExpense )
      {
         this.budgetExpense = budgetExpense;
      }
      #endregion

      #region Overrides
      /// <summary>
      /// Runs upon loading of the control
      /// </summary>
      /// <param name="e"></param>
      protected override void OnLoad(EventArgs e)
      {
         base.OnLoad(e);
         EnsureChildControls( );
      }

      /// <summary>
      /// Creates all child controls, applying styles, setting values, and binding validation
      /// </summary>
      protected override void CreateChildControls( )
      {
         costsList = new DropDownList( );
         inputCostAmount = new TextBox( );
         inputCostAmount.ID = "inputCostAmount";
         inputOtherCost = new TextBox( );
         inputOtherCost.ID = "inputOtherCost";
         applyOverhead = new CheckBox( );
         applyOverhead.Checked = budgetExpense.ApplyOverhead;
         delete = new CheckBox( );

         // Load the costs dropdown with refcodes
         System.Web.HttpApplicationState app = System.Web.HttpContext.Current.Application;
         ICachePolicy cachePolicy = (ICachePolicy)app[Policy.Names.ApplicationCachePolicyKey];
         CDS.RefCodes refCodes = (RefCodes)cachePolicy.GetCachedObject( RefCodes.CacheKey );
         ArrayList budgetStaffRoleCodes = refCodes.GetRefCodes( "ClinicalTrialBudgetExpense" );
         costsList.ID = "costsList";
         costsList.DataTextField = "Meaning";
         costsList.DataValueField = "Code";
         costsList.DataSource = budgetStaffRoleCodes;
         costsList.DataBind( );
         if ( String.IsNullOrEmpty( budgetExpense.StudyCostCode ) )
         {
            costsList.Items.Insert( 0, new ListItem( "", "" ) );
         }
         else
         {
            costsList.SelectedValue = budgetExpense.StudyCostCode;
         }
         costsList.AutoPostBack = true;
         costsList.SelectedIndexChanged += new EventHandler(OnSelectedIndexChanged);

         // Setup validators
         costFormatValidator = new RegularExpressionValidator( );
         costFormatValidator.ErrorMessage = "Cost must be a valid dollar amount.";
         costFormatValidator.Display = ValidatorDisplay.None;
         costFormatValidator.ControlToValidate = inputCostAmount.ID;
         costFormatValidator.ValidationExpression = @"\d+\.{0,1}\d{0,2}";

         costRequiredValidator = new RequiredFieldValidator( );
         costRequiredValidator.ErrorMessage = "Cost is required.";
         costRequiredValidator.Display = ValidatorDisplay.None;
         costRequiredValidator.ControlToValidate = inputCostAmount.ID;

         descriptionValidator = new RequiredFieldValidator( );
         descriptionValidator.ErrorMessage = "Description is required.";
         descriptionValidator.Display = ValidatorDisplay.None;
         descriptionValidator.ControlToValidate = costsList.ID;

         otherCostValidator = new RequiredFieldValidator( );
         otherCostValidator.ErrorMessage = "Description for other cost is required.";
         otherCostValidator.Display = ValidatorDisplay.None;
         otherCostValidator.ControlToValidate = inputOtherCost.ID;

         // Call OnSelectedIndexChanged to setup controls as if the value just changed
         // This keeps this processing consistent, since we may have just changed the value
         // during setup of the control
         OnSelectedIndexChanged( this, EventArgs.Empty );

         inputOtherCost.Text = budgetExpense.OtherExpenseText;
         if ( budgetExpense.ExpenseCost != null )
         {
            inputCostAmount.Text = decimal.Parse( budgetExpense.ExpenseCost ).ToString( "f" );
         }

         tr = new TableRow( );
         tdDescription = new TableCell( );
         tdDescription.Controls.Add( descriptionValidator );
         tdDescription.Controls.Add( otherCostValidator );
         tdDescription.Controls.Add( applyOverhead );
         tdDescription.Controls.Add( costsList );
         tdDescription.Controls.Add( inputOtherCost );

         tdCost = new TableCell( );
         tdCost.Controls.Add( costFormatValidator );
         tdCost.Controls.Add( costRequiredValidator );
         tdCost.Controls.Add( inputCostAmount );

         tdDelete = new TableCell( );
         tdDelete.Controls.Add( delete );
         
         tr.Controls.Add( tdDescription );
         tr.Controls.Add( tdCost );
         tr.Controls.Add( tdDelete );

         Controls.Add( tr );
      }

      /// <summary>
      /// Used to disable delete buttons for non-saved expenses
      /// </summary>
      protected override void OnPreRender(EventArgs e)
      {
         delete.Enabled = ( budgetExpense.Id != 0 );

         // Format numbers entered by the user
         if ( !String.IsNullOrEmpty(inputCostAmount.Text) )
            inputCostAmount.Text = decimal.Parse( inputCostAmount.Text ).ToString( "f" );

         base.OnPreRender (e);
      }

      #endregion

      #region Event Handlers
      /// <summary>
      /// Event handler to process changes to the Cost dropdown control.  Used to setup controls
      /// properly, both style and content, including validators.
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void OnSelectedIndexChanged(object sender, EventArgs e)
      {
         budgetExpense.StudyCostCode = costsList.SelectedValue;
         if ( !String.IsNullOrEmpty( budgetExpense.StudyCostCode ) && budgetExpense.StudyCostCode != "ClinicalTrialBudgetExpenseOther" )
         {
            // Pre-defined role selected, display rate and hide "other" controls
            System.Web.HttpApplicationState app = System.Web.HttpContext.Current.Application;
            ICachePolicy cachePolicy = (ICachePolicy)app[Policy.Names.ApplicationCachePolicyKey];
            CDS.RefCodes refCodes = (RefCodes)cachePolicy.GetCachedObject( RefCodes.CacheKey );
            RefCode refCode = refCodes.GetRefCode( "ClinicalTrialBudgetExpense", costsList.SelectedValue );
            if ( String.IsNullOrEmpty(inputCostAmount.Text) )
            {
               inputCostAmount.Text = refCode.Attributes["Rate"].ToString( );
            }
            costsList.CssClass = "ExpandControlWithCheckbox";
            inputOtherCost.CssClass = "ControlHidden";
            otherCostValidator.Enabled = false;
         }
         else if ( String.IsNullOrEmpty(budgetExpense.StudyCostCode) )
         {
            // new budgetStaff
            costsList.CssClass = "ExpandControlWithCheckbox";
            inputOtherCost.CssClass = "ControlHidden";
            otherCostValidator.Enabled = false;
         }
         else
         {
            // Other selected, enable controls
            costsList.CssClass = "ShortenControlWithCheckbox";
            inputOtherCost.CssClass = "ControlShown";
            otherCostValidator.Enabled = true;
         }
      }
      #endregion
   }

   #region Class BudgetExpenseControlDesigner
   /// <summary>
   /// Designer associated with the BudgetExpenseControl control.
   /// </summary>
   /// <remarks>
   /// This class cannot be used directly.
   /// </remarks>
   public class BudgetExpenseControlDesigner : ControlDesigner
   {
      #region Overrides
      /// <summary>
      /// Since the BudgetExpenseControl control does not have any design-time visibility, the designer provides
      /// the type name of that control and the name of the instance.
      /// </summary>
      /// <returns>HTML representation of the BudgetExpenseControl control</returns>
      public override string GetDesignTimeHtml( )
      {
         return CreatePlaceHolderDesignTimeHtml( );
      }
      #endregion
   }
   #endregion
}
